name: bun-macOS-aarch64

concurrency:
  group: bun-macOS-aarch64-${{ github.ref }}
  cancel-in-progress: true

env:
  LLVM_VERSION: 16
  BUN_DOWNLOAD_URL_BASE: https://pub-5e11e972747a44bf9aaf9394f185a982.r2.dev/releases/latest

on:
  push:
    branches: [main]
    paths:
      - "src/**/*"
      - "test/**/*"
      - "packages/bun-usockets/src/**/*"
      - "packages/bun-uws/src/**/*"
      - "CMakeLists.txt"
      - "build.zig"
      - "Makefile"
      - "Dockerfile"
  pull_request:
    branches: [main]
    paths:
      - "src/**/*"
      - "test/**/*"
      - "packages/bun-usockets/src/**/*"
      - "packages/bun-uws/src/**/*"
      - "CMakeLists.txt"
      - "build.zig"
      - "Makefile"
      - "Dockerfile"
  # Allows you to run this workflow manually from the Actions tab
  workflow_dispatch:

jobs:
  macOS-zig:
    name: macOS Zig Object
    runs-on: med-ubuntu
    if: github.repository_owner == 'oven-sh'
    strategy:
      matrix:
        include:
          - cpu: native
            arch: aarch64
            tag: bun-obj-darwin-aarch64
    steps:
      - uses: actions/checkout@v4
      # - name: Checkout submodules
      #   run: git submodule update --init --recursive --depth=1 --progress --force

      - name: Setup Docker Buildx
        uses: docker/setup-buildx-action@v3
        id: buildx
        with:
          install: true

      - name: Login to GitHub Container Registry
        uses: docker/login-action@v3
        with:
          registry: ghcr.io
          username: ${{ github.actor }}
          password: ${{ secrets.GITHUB_TOKEN }}

      - name: Compile Zig Object
        uses: docker/build-push-action@v5
        if: runner.arch == 'X64'
        with:
          context: .
          push: false
          # This doesnt seem to work
          # cache-from: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
          # cache-to: type=s3,endpoint_url=${{ secrets.CACHE_S3_ENDPOINT }},blobs_prefix=docker_blobs/,manifests_prefix=docker_manifests/,access_key_id=${{ secrets.CACHE_S3_ACCESS_KEY_ID }},secret_access_key=${{ secrets.CACHE_S3_SECRET_ACCESS_KEY }},bucket=bun,region=auto
          build-args: |
            BUILDARCH=${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
            BUILD_MACHINE_ARCH=${{ runner.arch == 'X64' && 'x86_64' || 'aarch64' }}
            ARCH=${{ matrix.arch }}
            CPU_TARGET=${{ matrix.cpu }}
            TRIPLET=${{ matrix.arch }}-macos-none
            GIT_SHA=${{ github.sha }}
          platforms: linux/${{ runner.arch == 'X64' && 'amd64' || 'arm64' }}
          target: build_release_obj
          outputs: type=local,dest=${{runner.temp}}/release

      - name: Upload Zig Object
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.tag }}
          path: ${{runner.temp}}/release/bun-zig.o

  macOS-dependencies:
    name: macOS Dependencies
    runs-on: ${{ matrix.runner }}
    if: github.repository_owner == 'oven-sh'
    timeout-minutes: 15
    strategy:
      matrix:
        include:
          - cpu: native
            arch: aarch64
            tag: bun-darwin-aarch64
            obj: bun-obj-darwin-aarch64
            artifact: bun-obj-darwin-aarch64
            runner: macos-13-xlarge
    steps:
      - uses: actions/checkout@v4
      - name: Checkout submodules
        run: git submodule update --init --recursive --depth=1 --progress --force

      - name: Install system dependencies
        env:
          HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
          HOMEBREW_NO_AUTO_UPDATE: 1
          HOMEBREW_NO_INSTALL_CLEANUP: 1
        run: |
          brew install go sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
          echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
          # echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
          echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
          echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
          brew link --overwrite llvm@$LLVM_VERSION

          curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-aarch64.zip"
          unzip bun-darwin-aarch64.zip
          mkdir -p ${{ runner.temp }}/.bun/bin
          mv bun-darwin-aarch64/bun ${{ runner.temp }}/.bun/bin/bun
          chmod +x ${{ runner.temp }}/.bun/bin/bun
          echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH

      - name: Hash submodule versions
        run: |
          print_data() {
            git submodule | grep -v WebKit
            llvm-config --version
            rustc --version
            cat $(echo scripts/build*.sh scripts/all-dependencies.sh | tr " " "\n" | sort)
          }
          echo "sha=$(print_data | sha1sum | cut -c 1-10)" >> $GITHUB_OUTPUT
        id: submodule-versions

      - name: Cache submodule dependencies
        id: cache-deps-restore
        uses: actions/cache/restore@v4
        with:
          path: ${{runner.temp}}/bun-deps
          key: bun-deps-${{ matrix.tag }}-${{ steps.submodule-versions.outputs.sha }}

      - name: Compile submodule dependencies
        if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
        env:
          CPU_TARGET: ${{ matrix.cpu }}
          BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
        run: |
          mkdir -p $BUN_DEPS_OUT_DIR
          bash ./scripts/clean-dependencies.sh
          bash ./scripts/all-dependencies.sh

      - name: Cache submodule dependencies
        if: ${{ !steps.cache-deps-restore.outputs.cache-hit }}
        id: cache-deps-save
        uses: actions/cache/save@v4
        with:
          path: ${{runner.temp}}/bun-deps
          key: ${{ steps.cache-deps-restore.outputs.cache-primary-key }}

      - name: Upload submodule dependencies
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.tag }}-deps
          path: ${{runner.temp}}/bun-deps

  macOS-cpp:
    name: macOS C++
    runs-on: ${{ matrix.runner }}
    if: github.repository_owner == 'oven-sh'
    timeout-minutes: 90
    strategy:
      matrix:
        include:
          - cpu: native
            arch: aarch64
            tag: bun-darwin-aarch64
            obj: bun-obj-darwin-aarch64
            artifact: bun-obj-darwin-aarch64
            runner: macos-13-xlarge
    steps:
      - uses: actions/checkout@v4
      - name: Checkout submodules
        run: git submodule update --init --recursive --depth=1 --progress --force

      - name: Install system dependencies
        env:
          HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
          HOMEBREW_NO_AUTO_UPDATE: 1
          HOMEBREW_NO_INSTALL_CLEANUP: 1
        run: |
          brew install go sccache ccache rust llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv automake openssl@1.1 ninja gnu-sed pkg-config --force
          echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
          # echo "$(brew --prefix sccache)/bin" >> $GITHUB_PATH
          echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
          echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
          brew link --overwrite llvm@$LLVM_VERSION

          curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-aarch64.zip"
          unzip bun-darwin-aarch64.zip
          mkdir -p ${{ runner.temp }}/.bun/bin
          mv bun-darwin-aarch64/bun ${{ runner.temp }}/.bun/bin/bun
          chmod +x ${{ runner.temp }}/.bun/bin/bun
          echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH

      # TODO: replace with sccache
      - name: ccache
        uses: hendrikmuhs/ccache-action@v1.2
        with:
          key: ${{ runner.os }}-ccache-${{ matrix.tag }}
          restore-keys: ${{ runner.os }}-ccache-${{ matrix.tag }}

      - name: Compile C++
        env:
          CPU_TARGET: ${{ matrix.cpu }}
          SOURCE_DIR: ${{ github.workspace }}
          OBJ_DIR: ${{ runner.temp }}/bun-cpp-obj
          BUN_DEPS_OUT_DIR: ${{runner.temp}}/bun-deps
        run: |
          mkdir -p $OBJ_DIR
          cd $OBJ_DIR

          cmake -S $SOURCE_DIR -B $OBJ_DIR \
            -G Ninja \
            -DCMAKE_BUILD_TYPE=Release \
            -DBUN_CPP_ONLY=1 \
            -DNO_CONFIGURE_DEPENDS=1

          bash compile-cpp-only.sh -v

      - name: Upload C++
        uses: actions/upload-artifact@v4
        with:
          name: ${{ matrix.tag }}-cpp
          path: ${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a
  macOS-link:
    name: macOS Link
    runs-on: ${{ matrix.runner }}
    if: github.repository_owner == 'oven-sh'
    needs: [macOS-zig, macOS-cpp, macOS-dependencies]
    timeout-minutes: 60
    permissions: write-all
    strategy:
      matrix:
        include:
          - cpu: native
            arch: aarch64
            tag: bun-darwin-aarch64
            obj: bun-obj-darwin-aarch64
            package: bun-darwin-aarch64
            artifact: bun-obj-darwin-aarch64
            runner: macos-13-xlarge
    steps:
      - uses: actions/checkout@v4
        with:
          submodules: recursive
          ref: ${{github.sha}}
          clean: true
      - name: Checkout submodules
        run: git submodule update --init --recursive --depth=1 --progress --force

      - name: Install system dependencies
        env:
          HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK: 1
          HOMEBREW_NO_AUTO_UPDATE: 1
          HOMEBREW_NO_INSTALL_CLEANUP: 1
        run: |
          brew install ccache llvm@$LLVM_VERSION pkg-config coreutils libtool cmake libiconv openssl@1.1 ninja --force
          echo "$(brew --prefix ccache)/bin" >> $GITHUB_PATH
          echo "$(brew --prefix coreutils)/libexec/gnubin" >> $GITHUB_PATH
          echo "$(brew --prefix llvm@$LLVM_VERSION)/bin" >> $GITHUB_PATH
          brew link --overwrite llvm@$LLVM_VERSION

          curl -LO "$BUN_DOWNLOAD_URL_BASE/bun-darwin-${{matrix.arch}}.zip"
          unzip bun-darwin-${{matrix.arch}}.zip
          mkdir -p ${{ runner.temp }}/.bun/bin
          mv bun-darwin-${{matrix.arch}}/bun ${{ runner.temp }}/.bun/bin/bun
          chmod +x ${{ runner.temp }}/.bun/bin/bun
          echo "${{ runner.temp }}/.bun/bin" >> $GITHUB_PATH

      - name: Download C++
        uses: actions/download-artifact@v4
        with:
          name: ${{ matrix.tag }}-cpp
          path: ${{ runner.temp }}/bun-cpp-obj

      - name: Download Zig Object
        uses: actions/download-artifact@v4
        with:
          name: ${{ matrix.obj }}
          path: ${{ runner.temp }}/release

      - name: Downloaded submodule dependencies
        uses: actions/download-artifact@v4
        with:
          name: ${{ matrix.tag }}-deps
          path: ${{runner.temp}}/bun-deps

      - name: Link
        env:
          CPU_TARGET: ${{ matrix.cpu }}
        run: |
          SRC_DIR=$PWD
          mkdir ${{runner.temp}}/link-build
          cd ${{runner.temp}}/link-build
          cmake $SRC_DIR \
            -G Ninja \
            -DCMAKE_BUILD_TYPE=Release \
            -DBUN_LINK_ONLY=1 \
            -DBUN_ZIG_OBJ="${{ runner.temp }}/release/bun-zig.o" \
            -DBUN_CPP_ARCHIVE="${{ runner.temp }}/bun-cpp-obj/bun-cpp-objects.a" \
            -DBUN_DEPS_OUT_DIR="${{runner.temp}}/bun-deps" \
            -DNO_CONFIGURE_DEPENDS=1
          ninja -v
      - name: Zip
        run: |
          cd ${{runner.temp}}/link-build
          chmod +x bun-profile bun

          mkdir -p ${{matrix.tag}}-profile/ ${{matrix.tag}}/

          mv bun-profile ${{matrix.tag}}-profile/bun-profile
          mv bun ${{matrix.tag}}/bun

          zip -r ${{matrix.tag}}-profile.zip ${{matrix.tag}}-profile
          zip -r ${{matrix.tag}}.zip ${{matrix.tag}}
      - uses: actions/upload-artifact@v4
        with:
          name: ${{matrix.tag}}-profile
          path: ${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip
      - uses: actions/upload-artifact@v4
        with:
          name: ${{matrix.tag}}
          path: ${{runner.temp}}/link-build/${{matrix.tag}}.zip
      - name: Release
        id: release
        uses: ncipollo/release-action@v1
        if: |
          github.repository_owner == 'oven-sh'
          && github.ref == 'refs/heads/main'
        with:
          prerelease: true
          body: "This canary release of Bun corresponds to the commit [${{ github.sha }}]"
          allowUpdates: true
          replacesArtifacts: true
          generateReleaseNotes: true
          artifactErrorsFailBuild: true
          token: ${{ secrets.GITHUB_TOKEN }}
          name: "Canary (${{github.sha}})"
          tag: "canary"
          artifacts: "${{runner.temp}}/link-build/${{matrix.tag}}.zip,${{runner.temp}}/link-build/${{matrix.tag}}-profile.zip"
      - uses: sarisia/actions-status-discord@v1
        if: failure() && github.repository_owner == 'oven-sh' && github.event_name == 'pull_request'
        with:
          title: ""
          webhook: ${{ secrets.DISCORD_WEBHOOK }}
          status: ${{ job.status }}
          noprefix: true
          nocontext: true
          description: |
            Pull Request
            ### [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})

            @${{ github.actor }}

            Build failed on ${{ matrix.tag }}:

            **[View build output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**

            [Commit ${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})
  macOS-test:
    name: Tests ${{matrix.tag}}
    runs-on: ${{ matrix.runner }}
    needs: [macOS-link]
    if: github.event_name == 'pull_request' && github.repository_owner == 'oven-sh'
    permissions:
      pull-requests: write
    timeout-minutes: 30
    outputs:
      failing_tests: ${{ steps.test.outputs.failing_tests }}
      failing_tests_count: ${{ steps.test.outputs.failing_tests_count }}
    strategy:
      fail-fast: false
      matrix:
        include:
          - tag: bun-darwin-aarch64
            runner: macos-13-xlarge
    steps:
      - id: checkout
        name: Checkout
        uses: actions/checkout@v4
        with:
          submodules: false
      - id: download
        name: Download
        uses: actions/download-artifact@v4
        with:
          name: ${{matrix.tag}}
          path: ${{runner.temp}}/release
      - id: install-bun
        name: Install Bun
        run: |
          cd ${{runner.temp}}/release
          unzip ${{matrix.tag}}.zip
          cd ${{matrix.tag}}
          chmod +x bun
          pwd >> $GITHUB_PATH
      - id: bun-version-check
        name: Bun version check
        run: |
          # If this hangs, it means something is seriously wrong with the build
          bun --version
      - id: install
        name: Install dependencies
        run: |
          bun install --verbose
          bun install --cwd=test --verbose
          bun install --cwd=packages/bun-internal-test --verbose
      - id: test
        name: Test (node runner)
        env:
          SMTP_SENDGRID_SENDER: ${{ secrets.SMTP_SENDGRID_SENDER }}
          TMPDIR: ${{runner.temp}}
          TLS_MONGODB_DATABASE_URL: ${{ secrets.TLS_MONGODB_DATABASE_URL }}
          TLS_POSTGRES_DATABASE_URL: ${{ secrets.TLS_POSTGRES_DATABASE_URL }}
        # if: ${{github.event.inputs.use_bun == 'false'}}
        run: |
          node packages/bun-internal-test/src/runner.node.mjs || true
      - uses: sarisia/actions-status-discord@v1
        if: always() && steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
        with:
          title: ""
          webhook: ${{ secrets.DISCORD_WEBHOOK }}
          status: "failure"
          noprefix: true
          nocontext: true
          description: |
            Pull Request
            ### ❌ [${{github.event.pull_request.title}}](https://github.com/oven-sh/bun/pull/${{github.event.number}})

            @${{ github.actor }}, there are ${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:

            ${{ steps.test.outputs.failing_tests }}

            **[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**
      - name: Comment on PR
        if: steps.test.outputs.failing_tests != '' && github.event_name == 'pull_request'
        uses: thollander/actions-comment-pull-request@v2
        with:
          comment_tag: test-failures-${{matrix.tag}}
          message: |
            ❌ @${{ github.actor }} ${{ steps.test.outputs.failing_tests_count }} files with test failures on ${{ matrix.tag }}:

            ${{ steps.test.outputs.failing_tests }}

            **[View test output](https://github.com/oven-sh/bun/actions/runs/${{github.run_id}})**

            <sup>[#${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})</sup>
      - name: Uncomment on PR
        if: steps.test.outputs.failing_tests == '' && github.event_name == 'pull_request'
        uses: thollander/actions-comment-pull-request@v2
        with:
          comment_tag: test-failures-${{matrix.tag}}
          mode: upsert
          create_if_not_exists: false
          message: |
            ✅ test failures on ${{ matrix.tag }} have been resolved.

            <sup>[#${{github.sha}}](https://github.com/oven-sh/bun/commits/${{github.sha}})</sup>
      - id: fail
        name: Fail the build
        if: steps.test.outputs.failing_tests != ''
        run: exit 1
